﻿using SkiaSharp;
using SkiaSharp.Views.WPF;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

namespace WPFSkiaDragDemo
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public SKTypeface Font;
        public Drag drawClock = new Drag();
        public double windowWidth = 0;
        public double windowHeight = 0;
        private bool isDraggingFromSidebar = false;
        private bool isDragging = false;
        // private SKElement skElement;
        
        public MainWindow()
        {
            InitializeComponent();
            //CreateUI();
            this.Loaded += (sender, e) =>
            {
                 windowWidth = this.ActualWidth;
                 windowHeight = this.ActualHeight;
                Console.WriteLine($"窗口宽度: {windowWidth}, 窗口高度: {windowHeight}");
                Canvas.SetLeft(skElement, 0);
                Canvas.SetTop(skElement, 0);
                // 实现 Width 绑定
                Binding widthBinding = new Binding("ActualWidth");
                widthBinding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Canvas), 1);
                skElement.SetBinding(SKElement.WidthProperty, widthBinding);
                // 实现 Height 绑定
                Binding heightBinding = new Binding("ActualHeight");
                heightBinding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Canvas), 1);
                skElement.SetBinding(SKElement.HeightProperty, heightBinding);

                double a = parentCanvas.ActualHeight;
                double d = parentCanvas.ActualWidth;
                double b = skElement.ActualHeight;
                double c = skElement.ActualWidth;
                Sidebar.ItemsSource = drawClock.SidebarPrimitives; // 绑定侧边栏数据
            };
            // 获取宋体在字体集合中的下标
            var index = SKFontManager.Default.FontFamilies.ToList().IndexOf("微软雅黑");
            // 创建宋体字形
            Font = SKFontManager.Default.GetFontStyles(index).CreateTypeface(0);
            //skElement = new SKElement();
            

            skElement.PaintSurface += SkContainer_PaintSurface;
            skElement.MouseDown += SkContainer_MouseDown;
            skElement.MouseUp += SkContainer_MouseUp;
            skElement.MouseMove += SkContainer_MouseMove;

            skElement.IgnorePixelScaling = false;
             _ = Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        Dispatcher.Invoke(() =>
                        {
                            skElement.InvalidateVisual();
                        });
                        _ = SpinWait.SpinUntil(() => false, 1000 / 60);//每秒60帧
                    }
                    catch
                    {
                        break;
                    }
                }
            });
        }
        private void Sidebar_PreviewMouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            // 获取点击的 ListBoxItem
            var listBox = sender as ListBox;
            var point = e.GetPosition(listBox);
            var item = FindVisualChild<ListBoxItem>(listBox, point);

            if (item != null)
            {
                var template = item.DataContext as Drag.PrimitiveTemplate;
                if (template != null)
                {

                    var skPoint = ConvertToSKPoint(e.GetPosition(skElement));
                    //var scale = VisualTreeHelper.GetDpi(skElement).DpiScaleX;
                    //var skPoint = new SKPoint((float)(point.X * scale), (float)(point.Y * scale));
                    drawClock.StartDragFromSidebar(template, skPoint);
                    isDraggingFromSidebar = true;
                    e.Handled = true;
                    Console.WriteLine($"Start Drag: {template.Name} at {skPoint}");

                }
            }
            
            
        }
        private void SkContainer_MouseDown(object sender, MouseEventArgs e)
        {
            //处理拖拽
            var scale = VisualTreeHelper.GetDpi(skElement).DpiScaleX;
            var position = e.GetPosition(skElement);
            if (!isDraggingFromSidebar) // 仅在非侧边栏拖拽时处理画布内拖拽
            {
                
                drawClock.MouseDown(new SKPoint((float)(position.X * scale), (float)(position.Y * scale)), true);
                Console.WriteLine($"SkContainer_MouseDown:仅在非侧边栏拖拽时处理画布内拖拽");
            }

            //处理属性修改
            // 转换鼠标坐标，考虑 DPI 缩放
            var skPoint = new SKPoint((float)(position.X * scale), (float)(position.Y * scale));

            Console.WriteLine($"Mouse Down at: ({skPoint.X}, {skPoint.Y})");

            //移除之前的输入控件
            if (drawClock.currentInputControl != null)
            {
                parentCanvas.Children.Remove(drawClock.currentInputControl);
                drawClock.currentInputControl = null;
            }
            if (drawClock.currentSwitchButton != null)
            {
                parentCanvas.Children.Remove(drawClock.currentSwitchButton);
                drawClock.currentSwitchButton = null;
            }

            foreach (var area in drawClock.interactiveAreas)
            {
                if (area.Rect.Contains(skPoint))
                {
                    area.OnClick?.Invoke(area.Rect);
                    break;
                }
            }

        }
        private void SkContainer_MouseUp(object sender, MouseEventArgs e)
        {
            var cur = e.GetPosition(skElement);
            var scale = VisualTreeHelper.GetDpi(skElement).DpiScaleX;
            var skPoint = new SKPoint((float)(cur.X * scale), (float)(cur.Y * scale));
            if (isDraggingFromSidebar)
            {
                drawClock.DropOnCanvas(skPoint);
                isDraggingFromSidebar = false;
            }
            else
            {
                drawClock.MouseDown(skPoint, false);
            }
            

        }
        private void SkContainer_MouseMove(object sender, MouseEventArgs e)
        {
            //图元移动
            var position = e.GetPosition(skElement);
            var scale = VisualTreeHelper.GetDpi(skElement).DpiScaleX;
            drawClock.MouseMove(new SKPoint((float)(position.X * scale), (float)(position.Y * scale)));
            if (isDraggingFromSidebar)
            {
                skElement.InvalidateVisual(); // 确保拖拽预览实时更新
            }

            //图元属性修改
            // 转换鼠标坐标，考虑 DPI 缩放
            //var skPoint = new SKPoint((float)position.X * drawClock.scaleX, (float)position.Y * drawClock.scaleY);
            var skPoint = new SKPoint((float)(position.X * scale), (float)(position.Y * scale));
            bool isOverAnyArea = false;
            foreach (var area in drawClock.interactiveAreas)
            {
                if (area.Rect.Contains(skPoint))
                {
                    skElement.Cursor = Cursors.Hand; // 鼠标悬停时显示手型光标
                    isOverAnyArea = true;
                    break;
                }
            }

            if (!isOverAnyArea)
            {
                skElement.Cursor = Cursors.Arrow; // 恢复默认光标
            }
        }

        private void SkContainer_PaintSurface(object? sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e)
        {
            var canvas = e.Surface.Canvas;
            //drawClock.Render(canvas, Font, 880, 180);
            drawClock.Render(parentCanvas,canvas,skElement, Font, (int)skElement.ActualWidth, (int)skElement.ActualHeight);
        }

        private void skElement_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e)
        {

        }
        private void SkElement_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var skPoint = ConvertToSKPoint(e.GetPosition(skElement));
            drawClock.SelectPrimitive(skPoint);
            if (drawClock.SelectedPrimitive != null)
            {
                isDragging = true;
                e.Handled = true;
                Console.WriteLine($"Selected primitive at {skPoint}");
            }
        }

        private void SkElement_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                var skPoint = ConvertToSKPoint(e.GetPosition(skElement));
                drawClock.UpdateDrag(skPoint);
                skElement.InvalidateVisual();
            }
        }

        private void SkElement_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (isDragging)
            {
                var skPoint = ConvertToSKPoint(e.GetPosition(skElement));
                drawClock.EndDrag(skPoint);
                isDragging = false;
                skElement.InvalidateVisual();
                Console.WriteLine($"Drop at {skPoint}");
            }
        }
        // 辅助方法：将 WPF 坐标转换为 SKPoint
        private SKPoint ConvertToSKPoint(Point point)
        {
            var scale = VisualTreeHelper.GetDpi(skElement).DpiScaleX;
            return new SKPoint((float)(point.X * scale), (float)(point.Y * scale));
        }

        // 辅助方法：查找点击的 ListBoxItem
        private T FindVisualChild<T>(DependencyObject parent, Point point) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                if (child is T target && IsPointInElement(child, point))
                {
                    return target;
                }
                var result = FindVisualChild<T>(child, point);
                if (result != null) return result;
            }
            return null;
        }
        private bool IsPointInElement(DependencyObject element, Point point)
        {
            if (element is UIElement uiElement)
            {
                var position = uiElement.TransformToAncestor(Sidebar).Transform(new Point(0, 0));
                var size = new Size(uiElement.RenderSize.Width, uiElement.RenderSize.Height);
                return point.X >= position.X && point.X <= position.X + size.Width &&
                       point.Y >= position.Y && point.Y <= position.Y + size.Height;
            }
            return false;
        }
    }
}
